hvm: Do not take shadow-emulation path if we are trying to inject an
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 22 Feb 2007 12:49:44 +0000 (12:49 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 22 Feb 2007 12:49:44 +0000 (12:49 +0000)
event into the HVM guest.
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/mm/shadow/multi.c
xen/include/asm-x86/hvm/hvm.h

index cff193c4cf0a93113c2870aaf273f87619e59e4f..a6dd6307f49df4ec2be361ed918b15dec8e83e51 100644 (file)
@@ -982,6 +982,12 @@ static void svm_hvm_inject_exception(
         v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2;
 }
 
+static int svm_injection_pending(struct vcpu *v)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    return (vmcb->vintr.fields.irq || vmcb->exitintinfo.fields.v);
+}
+
 int start_svm(void)
 {
     u32 eax, ecx, edx;
@@ -1058,6 +1064,8 @@ int start_svm(void)
     hvm_funcs.init_ap_context = svm_init_ap_context;
     hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
 
+    hvm_funcs.injection_pending = svm_injection_pending;
+
     hvm_enable();
 
     return 1;
index 0301781c18e3478cd13f90ab4220861d198bd193..017a818d1dedc5a6b1b83d9120de0d1dbd9f34a9 100644 (file)
@@ -990,6 +990,18 @@ static void vmx_update_vtpr(struct vcpu *v, unsigned long value)
     /* VMX doesn't have a V_TPR field */
 }
 
+static int vmx_injection_pending(struct vcpu *v)
+{
+    unsigned int idtv_info_field;
+
+    ASSERT(v == current);
+
+    idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
+
+    return (v->arch.hvm_vmx.vector_injected ||
+            (idtv_info_field & INTR_INFO_VALID_MASK));
+}
+
 /* Setup HVM interfaces */
 static void vmx_setup_hvm_funcs(void)
 {
@@ -1025,6 +1037,8 @@ static void vmx_setup_hvm_funcs(void)
     hvm_funcs.init_ap_context = vmx_init_ap_context;
 
     hvm_funcs.init_hypercall_page = vmx_init_hypercall_page;
+
+    hvm_funcs.injection_pending = vmx_injection_pending;
 }
 
 int start_vmx(void)
index f5b4e0eb3bbf3cec43441ae519be60b23273ee94..1f5cbb3aba1e03b33e5bceb0a858fb3454ec9fb7 100644 (file)
@@ -2901,18 +2901,35 @@ static int sh_page_fault(struct vcpu *v,
         goto not_a_shadow_fault;
 
     if ( is_hvm_domain(d) )
+    {
+        /*
+         * If we are in the middle of injecting an exception or interrupt then
+         * we should not emulate: it is not the instruction at %eip that caused
+         * the fault. Furthermore it is almost certainly the case the handler
+         * stack is currently considered to be a page table, so we should
+         * unshadow the faulting page before exiting.
+         */
+        if ( hvm_injection_pending(v) )
+        {
+            gdprintk(XENLOG_DEBUG, "write to pagetable during event "
+                     "injection: cr2=%#lx, mfn=%#lx\n", 
+                     va, mfn_x(gmfn));
+            sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
+            goto done;
+        }
+
         hvm_store_cpu_guest_regs(v, regs, NULL);
+    }
+
     SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n", 
                   (unsigned long)regs->eip, (unsigned long)regs->esp);
 
-    /* Check whether this looks like a stack operation. */
+    /*
+     * Check whether this looks like a stack operation.
+     * If so, forcibly unshadow and return.
+     */
     if ( (va & PAGE_MASK) == (regs->esp & PAGE_MASK) )
     {
-        /* Forcibly unshadow and return.  It's important to do this before
-         * we emulate: if the faulting stack operation was the guest handling
-         * an interrupt, then 
-         * (a) the instruction at %eip is irrelevant; and
-         * (b) we might inject some other fault and mask the real one */
         gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: "
                  "%%esp=%#lx, cr2=%#lx, mfn=%#lx\n", 
                  (unsigned long)regs->esp, va, mfn_x(gmfn));
index 125c73d2cee715fb47ec46ade5a6d8f2b93dc108..57c263a7b5f285cf0ec3b2a403142fbaa9b19d0c 100644 (file)
@@ -134,6 +134,8 @@ struct hvm_function_table {
                             int vcpuid, int trampoline_vector);
 
     void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
+
+    int  (*injection_pending)(struct vcpu *v);
 };
 
 extern struct hvm_function_table hvm_funcs;
@@ -262,4 +264,9 @@ hvm_inject_exception(unsigned int trapnr, int errcode, unsigned long cr2)
 
 int hvm_bringup_ap(int vcpuid, int trampoline_vector);
 
+static inline int hvm_injection_pending(struct vcpu *v)
+{
+    return hvm_funcs.injection_pending(v);
+}
+
 #endif /* __ASM_X86_HVM_HVM_H__ */